package com.dlc.shop.manager.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.BooleanUtil;
import com.dlc.shop.bean.app.dto.*;
import com.dlc.shop.bean.bo.PlatformCommissionOrderItemBO;
import com.dlc.shop.bean.dto.StockPointSkuDTO;
import com.dlc.shop.bean.enums.*;
import com.dlc.shop.bean.event.CheckAddrEvent;
import com.dlc.shop.bean.model.Category;
import com.dlc.shop.bean.model.Product;
import com.dlc.shop.bean.model.UserAddr;
import com.dlc.shop.bean.vo.*;
import com.dlc.shop.common.config.Constant;
import com.dlc.shop.common.constants.CacheNames;
import com.dlc.shop.common.constants.OrderCacheNames;
import com.dlc.shop.common.constants.StockPointType;
import com.dlc.shop.common.enums.StatusEnum;
import com.dlc.shop.common.exception.YamiShopBindException;
import com.dlc.shop.common.util.Arith;
import com.dlc.shop.common.util.BeanUtil;
import com.dlc.shop.common.util.CacheManagerUtil;
import com.dlc.shop.common.util.RedisUtil;
import com.dlc.shop.service.CategoryService;
import com.dlc.shop.service.SkuStockService;
import com.dlc.shop.service.UserAddrService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

import static com.dlc.shop.common.util.SpringContextUtils.applicationContext;

/**
 * 确认订单适配
 *
 * @author FrozenWatermelon
 * @date 2020/12/07
 */
@Slf4j
@Component
@AllArgsConstructor
public class ConfirmOrderManager {

    private final CacheManagerUtil cacheManagerUtil;
    private final CategoryService categoryService;
    private final UserAddrService userAddrService;
    private final SkuStockService skuStockService;


    /**
     * 过滤物流不同的商品
     *
     * @param shopCartOrderMerger 订单数据
     * @param userDeliveryInfoVO 地址数据
     * @param dbShopCartItems 用户选择的商品项
     * @return 返回过滤掉的商品项item
     */
    public List<ShopCartItemDto> filterShopItemsByType(ShopCartOrderMergerDto shopCartOrderMerger, UserDeliveryInfoVO userDeliveryInfoVO, List<ShopCartItemDto> dbShopCartItems) {
        if (CollUtil.isEmpty(dbShopCartItems)) {
            return new ArrayList<>();
        }
        String userId = shopCartOrderMerger.getUserId();

        // 根据商品物流模板判断是否用户地址是否在商品的配送范围
        if (CollUtil.isNotEmpty(dbShopCartItems)) {
            // 判断商品是否可配送
            CheckAddrEvent checkAddrEvent = new CheckAddrEvent(userDeliveryInfoVO.getUserAddr(), userId, null, dbShopCartItems);
            applicationContext.publishEvent(checkAddrEvent);
            // 商品物流模板集合
            userDeliveryInfoVO.setTransportMap(checkAddrEvent.getTransportMap());
        }

        Map<Long, Integer> dvyTypeMap = userDeliveryInfoVO.getDvyTypes().stream().collect(Collectors.toMap(DvyTypeDTO::getShopId, DvyTypeDTO::getDvyType));
        List<ShopCartItemDto> shopCartItems = new ArrayList<>();
        Set<ShopCartItemDto> devSet = new HashSet<>();
        for (ShopCartItemDto shopCartItem : dbShopCartItems) {
            Integer dvyType = dvyTypeMap.get(shopCartItem.getShopId());
            if (Objects.isNull(shopCartItem.getComboId())) {
                shopCartItem.setComboId(0L);
            }
            // 如果不是门店自提/同城配送，需要判断是否在配送范围
            if(!dvyType.equals(DvyType.STATION.value()) && !BooleanUtil.isTrue(shopCartItem.getIsDelivery()) && !dvyType.equals(DvyType.SAME_CITY.value())) {
                continue;
            }
            // 没有配置物流配送类型为无需配送，移除该订单项(非虚商品，虚拟商品不需要判断配送类型)
            // 实物或者组合商品 且 配送类型不一致， 则不能配送
            boolean realAndDelivery = !shopCartItem.getMold().equals(ProdMoldEnum.VIRTUAL.value()) && !deliverable(dvyType, shopCartItem);
            if (realAndDelivery) {
                continue;
            }
            //判断赠品的配送方式是否满足当前店铺的配送方式
            filterGiveawayShopItems(shopCartItem, dvyType);
            // 添加到可配送列表
            devSet.add(shopCartItem);
        }

        Map<Long, List<ShopCartItemDto>> shopCartItemMap = new HashMap<>(16);
        // 过滤订单项中，不可配送的商品
        filterDevShopCartItem(userDeliveryInfoVO, dbShopCartItems, shopCartItems, devSet, shopCartItemMap);

        // 获取过滤掉的商品项
        if (!Objects.equals(dbShopCartItems.size(), shopCartItems.size())) {
            dbShopCartItems.removeAll(shopCartItems);
            shopCartOrderMerger.setFilterShopItems(dbShopCartItems);
        } else {
            shopCartOrderMerger.setFilterShopItems(new ArrayList<>());
        }
        return shopCartItems;
    }

    private static void filterDevShopCartItem(UserDeliveryInfoVO userDeliveryInfoVO, List<ShopCartItemDto> dbShopCartItems, List<ShopCartItemDto> shopCartItems, Set<ShopCartItemDto> devSet, Map<Long, List<ShopCartItemDto>> shopCartItemMap) {
        for (ShopCartItemDto shopCartItem : dbShopCartItems) {
            // 普通商品直接处理了
            if (Objects.equals(shopCartItem.getComboId(), 0L)) {
                // 活动商品购买且不属于套餐活动
                if (Objects.equals(shopCartItem.getProdType(), ProdType.PROD_TYPE_ACTIVE.value())) {
                    // 活动商品不能单独购买
                    throw new YamiShopBindException("yami.active.prod.cannot.buy");
                }
                // 可配送列表包含该商品
                boolean confirmProd = devSet.contains(shopCartItem);
                // 是否只提交一个商品且是同城配送的商品(只提交一个商品且是同城配送的商品这种情况，不限制用户的地址是否满足配送，避免前端页面显示错误，结算订单的时候会再次判断是否满足配送)
                boolean isOnlyOneAndSameCity = dbShopCartItems.size() == 1 && Objects.equals(userDeliveryInfoVO.getDvyTypes().get(0).getDvyType(), DvyType.SAME_CITY.value());
                if (confirmProd || isOnlyOneAndSameCity || Objects.equals(shopCartItem.getMold(),ProdMoldEnum.VIRTUAL.value())) {
                    shopCartItems.add(shopCartItem);
                }
                continue;
            }
            // 过滤出实物商品
            int realItemSize = dbShopCartItems.stream().filter(item -> Objects.equals(item.getMold(),ProdMoldEnum.REAL.value()) && Objects.equals(item.getProdType(), ProdType.PROD_TYPE_NORMAL.value())).collect(Collectors.groupingBy(ShopCartItemDto::getProdId)).size();
            // 在商品详情也直接提交的套餐订单，没有购物车id，也仅有一个套餐
            boolean confirmCombo = (Objects.isNull(shopCartItem.getBasketId()) || shopCartItem.getBasketId() <= 0) && devSet.containsAll(dbShopCartItems);

            if (confirmCombo) {
                // 可配送列表中是否包含整个套餐，套餐是一个整体，只判断一次就行了
                if (devSet.containsAll(dbShopCartItems) || realItemSize == 1) {
                    shopCartItems.addAll(dbShopCartItems);
                }
                break;
            }
            // 套餐商品分组
            Long mainBasketId = shopCartItem.getBasketId();
            if (!Objects.equals(shopCartItem.getParentBasketId(), 0L)) {
                mainBasketId = shopCartItem.getParentBasketId();
            }
            List<ShopCartItemDto> shopCartItemList = shopCartItemMap.get(mainBasketId);
            if (Objects.isNull(shopCartItemList)) {
                shopCartItemList = new ArrayList<>();
                shopCartItemMap.put(mainBasketId, shopCartItemList);
            }
            shopCartItemList.add(shopCartItem);
        }
        for (Long basketId : shopCartItemMap.keySet()) {
            List<ShopCartItemDto> shopCartItemList = shopCartItemMap.get(basketId);
            // 套餐是一个整体，需要套餐中所有的商品都是可配送才能添加到订单列表
            if (devSet.containsAll(shopCartItemList)) {
                shopCartItems.addAll(shopCartItemList);
            }
        }
    }

    private boolean deliverable(Integer dvyType, ShopCartItemDto shopCartItem) {
        Product.DeliveryModeVO deliveryModeVO = shopCartItem.getDeliveryModeVO();
        boolean hasShopDelivery = deliveryModeVO.getHasShopDelivery() != null && Objects.equals(dvyType, DvyType.DELIVERY.value()) && deliveryModeVO.getHasShopDelivery();
        boolean hasUserPickUp = deliveryModeVO.getHasUserPickUp() != null && Objects.equals(dvyType, DvyType.STATION.value()) && deliveryModeVO.getHasUserPickUp();
        boolean hasCityDelivery = deliveryModeVO.getHasCityDelivery() != null && Objects.equals(dvyType, DvyType.SAME_CITY.value()) && deliveryModeVO.getHasCityDelivery();
        return hasShopDelivery || hasUserPickUp || hasCityDelivery;
    }

    private static void filterGiveawayShopItems(ShopCartItemDto shopCartItem, Integer dvyType) {
        if (CollUtil.isEmpty(shopCartItem.getGiveawayShopCartItemList())) {
            return;
        }
        Iterator<ShopCartItemDto> iterator = shopCartItem.getGiveawayShopCartItemList().iterator();
        while (iterator.hasNext()) {
            ShopCartItemDto shopCartItemDto = iterator.next();
            // 虚拟商品不需要判断物流
            if (Objects.equals(shopCartItemDto.getMold(), ProdMoldEnum.VIRTUAL.value())) {
                continue;
            }
            Product.DeliveryModeVO deliveryModeVO = shopCartItemDto.getDeliveryModeVO();
            // 赠品的配送方式要满足店铺的配送类型
            boolean canDelivary = (Objects.equals(DeliveryType.EXPRESS.getValue(), dvyType) && BooleanUtil.isTrue(deliveryModeVO.getHasShopDelivery())) ||
                    (Objects.equals(DeliveryType.STATION.getValue(), dvyType) && BooleanUtil.isTrue(deliveryModeVO.getHasUserPickUp())) ||
                    (Objects.equals(DeliveryType.SAME_CITY.getValue(), dvyType) && BooleanUtil.isTrue(deliveryModeVO.getHasCityDelivery()));
            // 不符合店铺配送类型的赠品，就不赠送了
            if (!canDelivary) {
                iterator.remove();
            }
        }
    }


    /**
     * 店铺营销活动计算完成后重算一次订单金额
     */
    public void recalculateAmountWhenFinishingCalculateShop(ShopCartOrderMergerDto shopCartOrderMerger, List<ShopCartDto> shopCarts, UserDeliveryInfoVO userDeliveryInfo) {
        Map<Long, ShopTransFeeVO> shopIdWithShopTransFee = userDeliveryInfo.getShopIdWithShopTransFee();
        // 所有店铺的订单信息
        List<ShopCartOrderDto> shopCartOrders = new ArrayList<>();
        double actualTotal = 0;
        double total = 0;
        int totalCount = 0;
        double allOrderReduce = 0;
        double totalTransFee = 0;
        //double supplierPriceTotal = 0;
        long scoreTotal = 0;
        Map<Long, Integer> shopCityStatusMap = new HashMap<>(16);
        if(Objects.nonNull(userDeliveryInfo.getShopCityStatusVoS())){
            shopCityStatusMap = userDeliveryInfo.getShopCityStatusVoS().stream().collect(Collectors.toMap(ShopCityStatusVO::getShopId, ShopCityStatusVO::getShopCityStatus));
        }
        Map<Long, Double> shopStartDeliveryFees = new HashMap<>(16);
        if(Objects.nonNull(userDeliveryInfo.getShopStartDeliveryFees())){
            shopStartDeliveryFees = userDeliveryInfo.getShopStartDeliveryFees();
        }
        // 所有店铺所有的商品item
        for (ShopCartDto shopCart : shopCarts) {
            // 每个店铺的订单信息
            ShopCartOrderDto shopCartOrder = new ShopCartOrderDto();
            shopCartOrder.setShopCityStatus(shopCityStatusMap.getOrDefault(shopCart.getShopId(), null));
            shopCartOrder.setStartDeliveryFee(shopStartDeliveryFees.containsKey(shopCart.getShopId()) ? shopStartDeliveryFees.get(shopCart.getShopId()): 0L);
            shopCartOrder.setOrderType(shopCartOrderMerger.getOrderType().value());
            shopCartOrder.setShopId(shopCart.getShopId());
            shopCartOrder.setShopName(shopCart.getShopName());
            shopCartOrder.setShopReduce(shopCart.getShopReduce());
            total = Arith.add(shopCart.getTotal(), total);
            totalCount += shopCart.getTotalCount();
            allOrderReduce = Arith.add(allOrderReduce, shopCart.getShopReduce());
            // 如果某家店因为各种优惠活动满减，使得金额变为负数，则这家店最低应该支付一分钱，而里面最贵的那件商品，也是支付一分钱，优惠金额 = （商品金额 - 一分钱）
            if (shopCart.getActualTotal() < 0.01 && !Objects.equals(shopCart.getShopId(), Constant.PLATFORM_SHOP_ID)) {
                shopCartOrder.setActualTotal(0.01);
                shopCartOrder.setShopReduce(Arith.sub(shopCart.getTotal(), 0.01));

                List<ShopCartItemDto> shopCartShopCartItem = getShopShopCartItem(shopCart.getShopCartItemDiscounts());
                resetActualTotal(shopCartShopCartItem);
            }
            //店铺优惠金额 = 优惠金额
            shopCartOrder.setShopReduce(shopCartOrder.getShopReduce());
            // 要计算运费
            totalTransFee = calculateTransFee(shopIdWithShopTransFee, totalTransFee, shopCart, shopCartOrder);
            // 店铺优惠券优惠金额
            shopCartOrder.setCouponReduce(shopCart.getCouponReduce());
            shopCartOrder.setShopComboAmount(shopCart.getComboReduce());
            shopCartOrder.setShopCartItemDiscounts(shopCart.getShopCartItemDiscounts());
            shopCartOrder.setCoupons(shopCart.getCoupons());
            shopCartOrder.setTotal(shopCart.getTotal());
            shopCartOrder.setTotalCount(shopCart.getTotalCount());
            actualTotal = Arith.add(actualTotal, shopCartOrder.getActualTotal());
            //supplierPriceTotal = Arith.add(supplierPriceTotal, shopCartOrder.getSupplierPriceTotal());
            if (Objects.equals(shopCartOrderMerger.getOrderType(), OrderType.SCORE)) {
                // 积分订单使用积分
                shopCartOrder.setUseScore(shopCart.getScoreTotal());
            } else {
                shopCartOrder.setUseScore(shopCartOrderMerger.getUsableScore());
            }
            shopCartOrder.setDiscountReduce(shopCart.getDiscountReduce());
            shopCartOrders.add(shopCartOrder);
            scoreTotal += shopCart.getScoreTotal();
        }
        shopCartOrderMerger.setActualTotal(actualTotal);
       // shopCartOrderMerger.setSupplierPriceTotal(supplierPriceTotal);
        shopCartOrderMerger.setTotal(total);
        shopCartOrderMerger.setTotalCount(totalCount);
        shopCartOrderMerger.setOrderReduce(allOrderReduce);
        shopCartOrderMerger.setTotalTransFee(totalTransFee);
        shopCartOrderMerger.setShopCartOrders(shopCartOrders);
        shopCartOrderMerger.setOrderSelfStationList(userDeliveryInfo.getOrderSelfStationList());
        shopCartOrderMerger.setUserAddr(BeanUtil.map(userDeliveryInfo.getUserAddr(), UserAddrDto.class));
        shopCartOrderMerger.setShopCityStatus(userDeliveryInfo.getShopCityStatus());
        shopCartOrderMerger.setFreeTransFee(userDeliveryInfo.getTotalFreeTransFee());
        shopCartOrderMerger.setStartDeliveryFee(userDeliveryInfo.getStartDeliveryFee());
        if (Objects.equals(shopCartOrderMerger.getOrderType(), OrderType.SCORE)) {
            shopCartOrderMerger.setUsableScore(scoreTotal);
        }
    }

    private double calculateTransFee(Map<Long, ShopTransFeeVO> shopIdWithShopTransFee, double totalTransFee, ShopCartDto shopCart, ShopCartOrderDto shopCartOrder) {
        if (shopIdWithShopTransFee != null && shopIdWithShopTransFee.containsKey(shopCartOrder.getShopId())) {
            ShopTransFeeVO shopTransFeeVO = shopIdWithShopTransFee.get(shopCartOrder.getShopId());

            // 店铺的实付 = 购物车实付 + 运费
            shopCartOrder.setActualTotal(shopCart.getActualTotal() + shopTransFeeVO.getTransFee());
            // 运费
            shopCartOrder.setTransFee(shopTransFeeVO.getTransFee());
            shopCartOrder.setFreeTransFee(shopTransFeeVO.getFreeTransFee());
            totalTransFee = Arith.add(totalTransFee, shopTransFeeVO.getTransFee());
        } else {
            // 运费
            shopCartOrder.setTransFee(0.0);
            shopCartOrder.setFreeTransFee(0.0);
            // 店铺的实付 = 购物车实付 + 运费
            shopCartOrder.setActualTotal(Arith.add(shopCart.getActualTotal(), shopCartOrder.getTransFee()));
        }
        //供应商价格
        //shopCartOrder.setSupplierPriceTotal(shopCart.getSupplierPriceTotal());
        return totalTransFee;
    }

    /**
     * 获取店铺下的所有订单
     */
    private List<ShopCartItemDto> getShopShopCartItem(List<ShopCartItemDiscountDto> shopCartItemDiscounts) {
        List<ShopCartItemDto> shopCartItemList = new ArrayList<>();
        for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartItemDiscounts) {
            shopCartItemList.addAll(shopCartItemDiscount.getShopCartItems());
        }
        shopCartItemList.sort(Comparator.comparingDouble(ShopCartItemDto::getActualTotal));
        return shopCartItemList;
    }


    /**
     * 重新计算金额，避免订单无法支付
     */
    private void resetActualTotal(List<ShopCartItemDto> shopCartShopCartItem) {
        Iterator<ShopCartItemDto> iterator = shopCartShopCartItem.iterator();
        while (iterator.hasNext()) {
            ShopCartItemDto shopCartItem = iterator.next();
            shopCartItem.setShareReduce(Arith.add(shopCartItem.getShareReduce(), Objects.isNull(shopCartItem.getPlatformShareReduce()) ? 0.0 : shopCartItem.getPlatformShareReduce()));
            shopCartItem.setActualTotal(Arith.sub(shopCartItem.getProductTotalAmount(), shopCartItem.getShareReduce()));
            if (iterator.hasNext()) {
                shopCartItem.setActualTotal(0.0);
                shopCartItem.setShareReduce(shopCartItem.getProductTotalAmount());
            } else {
                shopCartItem.setActualTotal(0.01);
                shopCartItem.setShareReduce(shopCartItem.getProductTotalAmount() - 0.01);
            }
        }
    }

    /**
     * 结束平台优惠的计算之后，还要重算一遍金额
     */
    public void recalculateAmountWhenFinishingCalculatePlatform(ShopCartOrderMergerDto shopCartOrderMergerDto) {
        List<VirtualRemarkVO> virtualRemarkList = new ArrayList<>();

        List<ShopCartOrderDto> shopCartOrders = shopCartOrderMergerDto.getShopCartOrders();
        List<ShopCartItemDto> allShopCartItem = new ArrayList<>();
        //所有订单实际金额
        double actualTotal = 0.00;
        //供应商总价
        double supplierPriceTotal = 0.00;
        //所有订单优惠金额
        double allOrderReduce = 0.00;
        double totalTransFee = 0.00;
        double totalShopFreeTransFee = 0.00;
        for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
            //订单实际金额
            double orderActualTotal = 0.00;
            //商家供应价格
            double ordersupplierPriceTotal = 0.00;
            //商家优惠金额
            double orderReduceAmount = 0.00;
            //商家满减优惠金额
            double couponAmount = 0.00;
            //商家优惠券优惠金额
            double discountAmount = 0.00;
            //平台优惠券优惠金额
            double platformCouponAmount = 0.00;
            //平台等级优惠金额
            double levelAmount = 0.00;
            //商家优惠金额
            double orderPlatformAmount = 0.00;
            // 满减金额计算
            List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCartOrder.getShopCartItemDiscounts();
            for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartItemDiscounts) {
                List<ShopCartItemDto> shopCartItems = shopCartItemDiscount.getShopCartItems();
                allShopCartItem.addAll(shopCartItems);
                for (ShopCartItemDto shopCartItem : shopCartItems) {
                    // 设置默认值
                    shopCartItem.setPlatformShareReduce(null == shopCartItem.getPlatformShareReduce() ? 0.0 : shopCartItem.getPlatformShareReduce());
                    shopCartItem.setPlatformShareReduce(Arith.roundByBanker(shopCartItem.getPlatformShareReduce(), 2));
                    shopCartItem.setShareReduce(Arith.add(Arith.roundByBanker(shopCartItem.getShareReduce(), 2), shopCartItem.getPlatformShareReduce()));
                    shopCartItem.setActualTotal(Arith.sub(shopCartItem.getProductTotalAmount(), shopCartItem.getShareReduce()));
                    orderActualTotal = Arith.add(orderActualTotal, shopCartItem.getActualTotal());
                    //设置供应商价格
                    ordersupplierPriceTotal = Arith.add(ordersupplierPriceTotal, shopCartItem.getSupplierPrice());
                    orderReduceAmount = Arith.add(orderReduceAmount, shopCartItem.getShareReduce());
                    orderPlatformAmount = Arith.addMayBeEmpty(orderPlatformAmount, shopCartItem.getPlatformShareReduce());
                    discountAmount = Arith.addMayBeEmpty(discountAmount, shopCartItem.getDiscountAmount());
                    couponAmount = Arith.addMayBeEmpty(couponAmount, shopCartItem.getShopCouponAmount());
                    platformCouponAmount = Arith.addMayBeEmpty(platformCouponAmount, shopCartItem.getPlatformCouponAmount());
                    levelAmount = Arith.addMayBeEmpty(levelAmount, shopCartItem.getLevelReduce());
                    if (CollectionUtil.isNotEmpty(shopCartItem.getVirtualRemarkList())) {
                        virtualRemarkList.addAll(shopCartItem.getVirtualRemarkList());
                    }
                }
            }
            shopCartOrder.setPlatformFreeFreightAmount(null == shopCartOrder.getPlatformFreeFreightAmount() ? 0.0 : shopCartOrder.getPlatformFreeFreightAmount());
            shopCartOrder.setActualTotal(Arith.sub(Arith.add(orderActualTotal, shopCartOrder.getTransFee()), shopCartOrder.getPlatformFreeFreightAmount()));
            //放入商家供应价格
            shopCartOrder.setSupplierPriceTotal(ordersupplierPriceTotal);
            //放入优惠金额
            shopCartOrder.setShopReduce(orderReduceAmount);
            //放入平台优惠金额,如果用户等级免自营店运费也要放进去
            shopCartOrder.setPlatformAmount(Arith.add(orderPlatformAmount, shopCartOrder.getPlatformFreeFreightAmount()));
            shopCartOrder.setCouponReduce(couponAmount);
            shopCartOrder.setDiscountReduce(discountAmount);
            shopCartOrder.setPlatformCouponReduce(platformCouponAmount);
            shopCartOrder.setLevelReduce(levelAmount);
            double transFee = Arith.sub(shopCartOrder.getTransFee(),shopCartOrder.getPlatformFreeFreightAmount());
            double shopActual = Arith.add(Arith.sub(shopCartOrder.getActualTotal(),transFee),shopCartOrder.getFreeTransFee());
            boolean checkMinAmount = shopActual < 0.01
                    && (shopCartOrder.getScoreReduce() == null || shopCartOrder.getScoreReduce() < 1L);
            // 如果是折扣特别小的情况下，导致实际金额为0，改变最小支付金额为0.01元,并且优惠金额减去0.01。
            if (checkMinAmount) {
                shopCartOrder.setActualTotal(Arith.add(shopCartOrder.getActualTotal(),0.01));
                shopCartOrder.setPlatformAmount(Arith.sub(shopCartOrder.getPlatformAmount(), 0.01));
                shopCartOrder.setShopReduce(Arith.sub(shopCartOrder.getShopReduce(), 0.01));
                // 并且如果等级优惠金额不为空，则在等级优惠金额减去，否则减去平台优惠券的分摊金额
                if (shopCartOrderMergerDto.getTotalLevelAmount() > 0.00) {
                    shopCartOrderMergerDto.setTotalLevelAmount(Arith.sub(shopCartOrderMergerDto.getTotalLevelAmount(), 0.01));
                    shopCartOrder.setLevelReduce(Arith.sub(shopCartOrder.getLevelReduce(), 0.01));
                    // 按照抵扣金额大小排序，扣除最大的那个商品项的等级优惠金额0.01元
                    List<ShopCartItemDto> items = allShopCartItem.stream().sorted(Comparator.comparing(ShopCartItemDto::getLevelReduce).reversed()).toList();
                    ShopCartItemDto shopCartItemDto = items.get(0);
                    shopCartItemDto.setActualTotal(0.01);
                    shopCartItemDto.setPlatformShareReduce(Arith.sub(shopCartItemDto.getPlatformShareReduce(), 0.01));
                    shopCartItemDto.setShareReduce(Arith.sub(shopCartItemDto.getShareReduce(), 0.01));
                    shopCartItemDto.setLevelReduce(Arith.sub(shopCartItemDto.getLevelReduce(),0.01));
                }
            }
            // 加上（店铺运费优惠金额+平台运费优惠金额）
            shopCartOrder.setShopReduce(Arith.add(Arith.add(shopCartOrder.getShopReduce(), shopCartOrder.getPlatformFreeFreightAmount()), shopCartOrder.getFreeTransFee()));
            actualTotal = Arith.add(actualTotal, shopCartOrder.getActualTotal());
            supplierPriceTotal = Arith.add(supplierPriceTotal, shopCartOrder.getSupplierPriceTotal());
            allOrderReduce = Arith.add(allOrderReduce, shopCartOrder.getShopReduce());
            totalTransFee = Arith.add(totalTransFee, shopCartOrder.getTransFee());
            totalShopFreeTransFee = Arith.add(totalShopFreeTransFee, shopCartOrder.getFreeTransFee());
        }

        shopCartOrderMergerDto.setActualTotal(actualTotal);
        //供应商总价
        shopCartOrderMergerDto.setSupplierPriceTotal(supplierPriceTotal);
        shopCartOrderMergerDto.setOrderReduce(allOrderReduce);
        shopCartOrderMergerDto.setTotalTransFee(totalTransFee);
        shopCartOrderMergerDto.setShopFreeTransFee(totalShopFreeTransFee);
        shopCartOrderMergerDto.setShopCartOrders(shopCartOrders);
        shopCartOrderMergerDto.setVirtualRemarkList(virtualRemarkList);
    }

    /**
     * 计算平台佣金，积分订单不可用
     */
    public void calculatePlatformCommission(ShopCartOrderMergerDto shopCartOrderMerger) {
        List<ShopCartOrderDto> shopCartOrders = shopCartOrderMerger.getShopCartOrders();
        for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
            double platformCommission = 0.00;
            List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCartOrder.getShopCartItemDiscounts();
            for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartItemDiscounts) {
                List<ShopCartItemDto> shopCartItems = shopCartItemDiscount.getShopCartItems();
                List<PlatformCommissionOrderItemBO> platformCommissionShopCartItems = new ArrayList<>();
                for (ShopCartItemDto shopCartItem : shopCartItems) {
                    PlatformCommissionOrderItemBO platformCommissionOrderItem = new PlatformCommissionOrderItemBO();
                    platformCommissionOrderItem.setShopId(shopCartItem.getShopId());
                    platformCommissionOrderItem.setCategoryId(shopCartItem.getCategoryId());
                    platformCommissionOrderItem.setSkuId(shopCartItem.getSkuId());
                    platformCommissionShopCartItems.add(platformCommissionOrderItem);
                }
                // 获取整个平台的佣金比例
                List<Category> categoryRates = categoryService.listRate();
                List<PlatformCommissionOrderItemBO> data = categoryService.calculatePlatformCommission(platformCommissionShopCartItems, categoryRates);
                Map<Long, PlatformCommissionOrderItemBO> categoryMap = data.stream().collect(Collectors.toMap(PlatformCommissionOrderItemBO::getSkuId, p -> p));
                for (ShopCartItemDto shopCartItem : shopCartItems) {
                    PlatformCommissionOrderItemBO platformCommissionOrderItem = categoryMap.get(shopCartItem.getSkuId());
                    // 分摊比例
                    shopCartItem.setRate(platformCommissionOrderItem.getRate());
                    // 平台佣金 = （实付金额 + 平台优惠金额） * 比例 / 100
                    double itemPlatformCommission = Arith.roundByBanker(Arith.div(Arith.mul(Arith.add(shopCartItem.getActualTotal(), shopCartItem.getPlatformShareReduce()),
                            platformCommissionOrderItem.getRate()), 100), 2);
                    shopCartItem.setPlatformCommission(itemPlatformCommission);
                    platformCommission = Arith.add(platformCommission, itemPlatformCommission);
                }
            }
            shopCartOrder.setPlatformCommission(platformCommission);
        }
    }

    public void cacheCalculatedInfo(String userId, ShopCartOrderMergerDto shopCartOrderMerger) {
        // 防止重复提交
        RedisUtil.STRING_REDIS_TEMPLATE.opsForValue().set(OrderCacheNames.ORDER_CONFIRM_UUID_KEY + CacheNames.UNION + userId, String.valueOf(userId));
        // 保存订单计算结果缓存，省得重新计算 并且 用户确认的订单金额与提交的一致
        cacheManagerUtil.putCache(OrderCacheNames.ORDER_CONFIRM_KEY, String.valueOf(userId), shopCartOrderMerger);
    }

    public void reCalAmountWhenFinishCalShop(ShopCartOrderMergerDto shopCartOrderMergerDto) {
        double itemAmount;
        double orderAmount;
        double allOrderAmount = 0.0;
        double totalFreeTranFee = 0.0;
        double totalTranFee = 0.0;
        // 重新计算商品、订单、总订单的价格
        for (ShopCartOrderDto order : shopCartOrderMergerDto.getShopCartOrders()) {
            orderAmount = 0.0;
            for (ShopCartItemDiscountDto itemCoupon : order.getShopCartItemDiscounts()) {
                for (ShopCartItemDto item : itemCoupon.getShopCartItems()) {
                    itemAmount = Arith.sub(item.getActualTotal(), item.getShopMemberAmount());
                    item.setShareReduce(Arith.add(item.getShareReduce(), item.getShopMemberAmount()));
                    item.setActualTotal(itemAmount);
                    orderAmount = Arith.add(orderAmount, itemAmount);
                }
            }
            orderAmount = Arith.add(orderAmount, order.getTransFee());
            order.setActualTotal(orderAmount);
            order.setShopReduce(Arith.add(order.getShopReduce(), order.getShopMemberAmount()));
            allOrderAmount = Arith.add(allOrderAmount, orderAmount);
            totalFreeTranFee = Arith.add(totalFreeTranFee, order.getFreeTransFee());
            totalTranFee = Arith.add(totalTranFee, order.getTransFee());
        }
        if (Objects.equals(shopCartOrderMergerDto.getOrderType().value(), OrderType.ORDINARY.value())) {
            double orderShopReduce = Objects.isNull(shopCartOrderMergerDto.getOrderReduce()) ? 0.0 : shopCartOrderMergerDto.getOrderReduce();
            shopCartOrderMergerDto.setOrderShopReduce(Arith.add(orderShopReduce,shopCartOrderMergerDto.getShopMemberAmount()));
        } else {
            shopCartOrderMergerDto.setOrderShopReduce(0.0);
        }
        shopCartOrderMergerDto.setActualTotal(allOrderAmount);
        shopCartOrderMergerDto.setTotalTransFee(totalTranFee);
        shopCartOrderMergerDto.setShopFreeTransFee(totalFreeTranFee);
    }


    public UserDeliveryInfoVO getUserDeliveryInfoVO(List<ShopCartItemDto> shopCartItemsDb, String userId, List<DvyTypeDTO> dvyTypes, Long addrId) {
        UserDeliveryInfoVO userDeliveryInfoVO = new UserDeliveryInfoVO();
        setWarehouseMapByOrderItems(shopCartItemsDb, userDeliveryInfoVO);
        userDeliveryInfoVO.setAddrId(addrId);
        userDeliveryInfoVO.setDvyTypes(dvyTypes);
        DvyTypeDTO dvyTypeDTO = dvyTypes.get(0);

        // 没有订单项或者是自提订单，处理完直接返回即可，不需要获取用户地址
        if (CollectionUtil.isEmpty(shopCartItemsDb) || Objects.equals(dvyTypeDTO.getDvyType(), DeliveryType.STATION.getValue())) {
            // 自提订单，将自提相关的参数插入地址信息中
            if (Objects.equals(dvyTypeDTO.getDvyType(), DeliveryType.STATION.getValue())) {
                userDeliveryInfoVO.setStationId(dvyTypeDTO.getStationId());
                OrderSelfStationDto orderSelfStation = new OrderSelfStationDto();
                orderSelfStation.setLat(dvyTypeDTO.getLat());
                orderSelfStation.setLng(dvyTypeDTO.getLng());
                orderSelfStation.setStationId(userDeliveryInfoVO.getStationId());
                userDeliveryInfoVO.setOrderSelfStation(orderSelfStation);
            }
        }

        // 不是自提订单，获取用户id
        if (Objects.equals(dvyTypeDTO.getDvyType(), DeliveryType.STATION.getValue())) {
            return userDeliveryInfoVO;
        }
        // 获取用户地址信息
        UserAddr userAddr = userAddrService.getUserAddrByUserId(addrId, userId);
        if (userAddr == null) {
            log.info("用户选择物流配送，获取用户地址信息为空");
            userDeliveryInfoVO.setTotalFreeTransFee(0D);
            userDeliveryInfoVO.setTotalTransFee(0D);
            userDeliveryInfoVO.setShopCityStatus(-1);
        }
        log.info("订单用户地址信息 -- userAddr:{}", userAddr);
        userDeliveryInfoVO.setUserAddr(userAddr);
        return userDeliveryInfoVO;
    }

    public Map<Long, List<WarehouseVO>> setWarehouseMapByOrderItems(List<ShopCartItemDto> shopCartItems, UserDeliveryInfoVO userDeliveryInfoVO) {
        if (MapUtil.isNotEmpty(userDeliveryInfoVO.getWarehouseMap())) {
            return userDeliveryInfoVO.getWarehouseMap();
        }
        Map<Long, List<WarehouseVO>> warehouseMap = new HashMap<>(Constant.INITIAL_CAPACITY);
        for (ShopCartItemDto shopCartItem : shopCartItems) {
            if (CollUtil.isNotEmpty(shopCartItem.getWarehouseList())) {
                warehouseMap.put(shopCartItem.getShopId(), shopCartItem.getWarehouseList());
                shopCartItem.setWarehouseList(null);
            }
            if (CollUtil.isEmpty(shopCartItem.getComboShopCartItems())) {
                continue;
            }
            for (ShopCartItemDto comboShopCartItem : shopCartItem.getComboShopCartItems()) {
                if (CollUtil.isNotEmpty(comboShopCartItem.getWarehouseList())) {
                    warehouseMap.put(comboShopCartItem.getShopId(), comboShopCartItem.getWarehouseList());
                    comboShopCartItem.setWarehouseList(null);
                }
            }
        }
        userDeliveryInfoVO.setWarehouseMap(warehouseMap);
        return warehouseMap;
    }

    public void handleShopCartStockPoint(UserDeliveryInfoVO userDeliveryInfoVO, List<ShopCartDto> shopCarts, List<ShopCartItemDto> shopCartItemsDb, Integer mold) {
        Map<Long, Integer> dvyTypeMap = userDeliveryInfoVO.getDvyTypes().stream().collect(Collectors.toMap(DvyTypeDTO::getShopId, DvyTypeDTO::getDvyType));
        List<ShopCartItemDto> shopCartItems = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (ShopCartDto shopCart : shopCarts) {
            for (ShopCartItemDiscountDto shopCartItemDiscount : shopCart.getShopCartItemDiscounts()) {
                for (ShopCartItemDto shopCartItem : shopCartItemDiscount.getShopCartItems()) {
                    if (CollUtil.isNotEmpty(shopCartItem.getComboShopCartItems())) {
                        shopCartItems.addAll(shopCartItem.getComboShopCartItems());
                        shopCartItem.setStockPointList(shopCartItem.getComboShopCartItems().get(0).getStockPointList());
                    }
                    shopCartItems.add(shopCartItem);
                }
            }
        }
        Map<Long, List<WarehouseVO>> warehouseMap = setWarehouseMapByOrderItems(shopCartItemsDb, userDeliveryInfoVO);
        for (ShopCartItemDto shopCartItem : shopCartItemsDb) {
            if (CollUtil.isEmpty(shopCartItem.getGiveawayShopCartItemList()) || !Objects.equals(shopCartItem.getMold(), ProdMoldEnum.COMBO.value())) {
                continue;
            }
            shopCartItems.addAll(shopCartItem.getGiveawayShopCartItemList());
        }
        Long areaId = null;
        if (Objects.nonNull(userDeliveryInfoVO.getUserAddr())) {
            areaId = userDeliveryInfoVO.getUserAddr().getAreaId();
        }
        // 非虚拟商品或者自提订单，且用户未选择订单地址，等用户选择地址后再获取快递配送的仓库
        boolean noAddr =  !Objects.equals(mold, ProdMoldEnum.VIRTUAL.value()) && !Objects.equals(userDeliveryInfoVO.getDvyTypes().get(0).getDvyType(), DeliveryType.STATION.getValue());
        if (Objects.isNull(areaId) && noAddr) {
            return;
        }

        Map<String, SkuStockVO> giveawayStockMap = new HashMap<>(Constant.INITIAL_CAPACITY);
        for (ShopCartItemDto shopCartItem : shopCartItems) {
            if(CollectionUtil.isEmpty(shopCartItem.getStockPointList())){
                continue;
            }
            Integer dvyType = dvyTypeMap.get(shopCartItem.getShopId());
            if(Objects.equals(shopCartItem.getMold(), ProdMoldEnum.COMBO.value())) {
                // 使用默认仓库id
                continue;
            }
            List<WarehouseVO> warehouseList = warehouseMap.get(shopCartItem.getShopId());
            shopCartItem.setStockPointType(StockPointType.WAREHOUSE.getValue());
            // 商品满足以下任意一项则使用默认仓库的库存：仅有默认仓库的sku、虚拟商品、同城配送、积分商品
            boolean defaultPoint = Objects.equals(shopCartItem.getMold(), ProdMoldEnum.VIRTUAL.value()) ||
                    Objects.equals(shopCartItem.getProdType(), ProdType.PROD_TYPE_SCORE.value()) ||
                    Objects.equals(dvyType, DeliveryType.SAME_CITY.getValue());
            if (defaultPoint) {
                // 使用默认仓库id
                continue;
            }

            if (Objects.equals(dvyType, DeliveryType.STATION.getValue())) {
                // 用户自提 - 判断是共享总部库存还是门店是独立销售库存
                // 默认是共享总部库存，也就是默认仓库id
                Long stationId = shopCartItem.getStockPointId();
                for (StockPointSkuDTO stockPointSku : shopCartItem.getStockPointList()) {
                    // 门店是独立销售库存，则使用门店id
                    boolean useStationStock = Objects.equals(stockPointSku.getStockPointId(), userDeliveryInfoVO.getStationId()) &&
                            Objects.equals(stockPointSku.getStockPointType(), StockPointType.STATION.getValue()) &&
                            Objects.equals(stockPointSku.getStockMode(), StockModeEnum.SINGLE_STOCK.value());
                    if (useStationStock) {
                        stationId = stockPointSku.getStockPointId();
                        // 仓库类型更改为门店
                        shopCartItem.setStockPointType(StockPointType.STATION.getValue());
                        break;
                    }
                }
                shopCartItem.setStockPointId(stationId);
                shopCartItem.setStockPointType(StockPointType.STATION.getValue());
                continue;
            }
            // 未设置库存区域id的订单项
            setStockPointId(warehouseList, shopCartItem, areaId);

        }
        for (ShopCartItemDto shopCartItem : shopCartItems) {
            shopCartItem.setStockPointList(null);
            // 加载完仓库id后，再校验是否为赠品 - 组合商品没有赠品
            if (CollUtil.isEmpty(shopCartItem.getGiveawayShopCartItemList())) {
                continue;
            }
            for (ShopCartItemDto giveawayShopCartItem : shopCartItem.getGiveawayShopCartItemList()) {
                // 赠品必须跟主商品一个仓库
                giveawayShopCartItem.setStockPointId(shopCartItem.getStockPointId());
                // 赠品需要判断库存，所以先收集赠品的库存信息
                String stockKey = giveawayShopCartItem.getSkuId() + Constant.UNDERLINE + giveawayShopCartItem.getStockPointId();
                if (giveawayStockMap.containsKey(stockKey)) {
                    continue;
                }
                SkuStockVO skuStockVO = new SkuStockVO(giveawayShopCartItem.getSkuId());
                skuStockVO.setStockPointId(giveawayShopCartItem.getStockPointId());
                giveawayStockMap.put(stockKey, skuStockVO);
            }
        }
        shopCartItems.forEach(shopCartItemVO -> shopCartItemVO.setWarehouseList(null));
        // 校验赠品库存，并去除库存不足的赠品
        this.checkGiveawayStock(shopCartItems, shopCarts, shopCartItemsDb, giveawayStockMap);
    }


    private static void setStockPointId(List<WarehouseVO> warehouseList, ShopCartItemDto shopCartItem, Long areaId) {
        // 匹配区域仓库，如果地址在区域仓库的范围内，就更换为区域仓库的id
        for (WarehouseVO warehouseVO : warehouseList) {
            // 默认仓库不处理
            if (Objects.equals(warehouseVO.getType(), 0)) {
                continue;
            }
            // 用户订单地址包含在仓库配送区域内，则使用区域库存id
            if (warehouseVO.getAreaIds().contains(areaId)) {
                shopCartItem.setStockPointId(warehouseVO.getWarehouseId());
                shopCartItem.setStockPointType(StockPointType.WAREHOUSE.getValue());
                return;
            }

        }
    }

    private void checkGiveawayStock(List<ShopCartItemDto> shopCartItems, List<ShopCartDto> shopCarts, List<ShopCartItemDto> shopCartItemsDb, Map<String, SkuStockVO> giveawayStockMap) {
        // 没有赠品，不需要检验赠品库存
        if (giveawayStockMap.isEmpty()) {
            return;
        }
        // 查询赠品的库存
        Map<String, SkuStockVO> skuStockMap = skuStockService.listSkuStock(new ArrayList<>(giveawayStockMap.values()));
        // 先扣除主商品的库存
        for (ShopCartItemDto shopCartItemVO : shopCartItems) {
            // 这里是主商品的库存扣除，赠品先跳过不处理
            if (Objects.nonNull(shopCartItemVO.getGiveawayRefundPrice())) {
                continue;
            }
            String stockKey = shopCartItemVO.getSkuId() + Constant.UNDERLINE + shopCartItemVO.getStockPointId();
            // 没有跟赠品相同的区域库存，就不用操作
            if (!skuStockMap.containsKey(stockKey)) {
                continue;
            }
            SkuStockVO skuStockVO = skuStockMap.get(stockKey);
            // sku库存先扣除主商品的购买数量
            skuStockVO.setStock(skuStockVO.getStock() - shopCartItemVO.getProdCount());
            // sku库存数量不足或者不是启用状态
            if (skuStockVO.getStock() <= 0 || !Objects.equals(skuStockVO.getStatus(), StatusEnum.ENABLE.value())) {
                skuStockMap.remove(stockKey);
            }
        }
        // 扣完主商品的库存后，按顺序开始扣除赠品的库存

        // 先扣除组合商品的赠品库存
        for (ShopCartItemDto shopCartItemVO : shopCartItemsDb) {
            if (Objects.equals(shopCartItemVO.getMold(), ProdMoldEnum.COMBO.value())) {
                handleGiveaway(skuStockMap, shopCartItemVO);
            }
        }
        // 再扣除普通商品
        for (ShopCartDto shopCart : shopCarts) {
            for (ShopCartItemDiscountDto shopCartItemDiscount : shopCart.getShopCartItemDiscounts()) {
                for (ShopCartItemDto shopCartItemVO : shopCartItemDiscount.getShopCartItems()) {
                    handleGiveaway(skuStockMap, shopCartItemVO);
                }
            }
        }
    }
    private static void handleGiveaway(Map<String, SkuStockVO> skuStockMap, ShopCartItemDto shopCartItemDto) {
        // 没有赠品的购物车项，跳过处理
        if (CollUtil.isEmpty(shopCartItemDto.getGiveawayShopCartItemList())) {
            return;
        }
        // 删除没有足够库存的赠品项
        shopCartItemDto.getGiveawayShopCartItemList().removeIf(giveawayShopCartItem -> {
            String stockKey = giveawayShopCartItem.getSkuId() + Constant.UNDERLINE + giveawayShopCartItem.getStockPointId();
            // 没有跟赠品的区域库存，代表库存数量不足, 删除该赠品
            if (!skuStockMap.containsKey(stockKey)) {
                return true;
            }
            SkuStockVO skuStockVO = skuStockMap.get(stockKey);
            // 扣除赠品库存
            skuStockVO.setStock(skuStockVO.getStock() - giveawayShopCartItem.getProdCount());
            // sku库存数量不足，删除该赠品
            if (skuStockVO.getStock() <= 0) {
                return true;
            }
            return false;
        });
    }

}
